11. 开发你的第一个Spring Boot应用

我们将使用Java开发一个简单的"Hello World" web应用,以此强调下Spring Boot的一些关键特性。项目采用Maven进行构建,因为大多数IDEs都支持它。

spring.io网站包含很多Spring Boot"入门"指南,如果你正在找特定问题的解决方案,可以先去那瞅瞅。你也可以简化下面的步骤,直接从start.spring.io的依赖搜索器选中web starter,这会自动生成一个新的项目结构,然后你就可以happy的敲代码了。具体详情参考文档

在开始前,你需要打开终端检查下安装的Java和Maven版本是否可用:

$ java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)
$ mvn -v
Apache Maven 3.2.3 (33f8c3e1027c3ddde99d3cdebad2656a31e8fdf4; 2014-08-11T13:58:10-07:00)
Maven home: /Users/user/tools/apache-maven-3.1.1
Java version: 1.7.0_51, vendor: Oracle Corporation

:该示例需要创建单独的文件夹,后续的操作建立在你已创建一个合适的文件夹,并且它是你的“当前目录”。

11.1. 创建POM

让我们以创建一个Maven pom.xml文件作为开始吧,因为pom.xml是构建项目的处方!打开你最喜欢的文本编辑器,并添加以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>myproject</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.1.BUILD-SNAPSHOT</version>
    </parent>

    <!-- Additional lines to be added here... -->

    <!-- (you don't need this if you are using a .RELEASE version) -->
    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <url>http://repo.spring.io/snapshot</url>
            <snapshots><enabled>true</enabled></snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <url>http://repo.spring.io/milestone</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <url>http://repo.spring.io/snapshot</url>
        </pluginRepository>
        <pluginRepository>
            <id>spring-milestones</id>
            <url>http://repo.spring.io/milestone</url>
        </pluginRepository>
    </pluginRepositories>
</project>

这样一个可工作的构建就完成了,你可以通过运行mvn package测试它(暂时忽略"jar将是空的-没有包含任何内容!"的警告)。

:此刻,你可以将该项目导入到IDE中(大多数现代的Java IDE都包含对Maven的内建支持)。简单起见,我们将继续使用普通的文本编辑器完成该示例。

11.2. 添加classpath依赖

Spring Boot提供很多"Starters",用来简化添加jars到classpath的操作。示例程序中已经在POM的parent节点使用了spring-boot-starter-parent,它是一个特殊的starter,提供了有用的Maven默认设置。同时,它也提供一个dependency-management节点,这样对于期望(”blessed“)的依赖就可以省略version标记了。

其他”Starters“只简单提供开发特定类型应用所需的依赖。由于正在开发web应用,我们将添加spring-boot-starter-web依赖-但在此之前,让我们先看下目前的依赖:

$ mvn dependency:tree
[INFO] com.example:myproject:jar:0.0.1-SNAPSHOT

mvn dependency:tree命令可以将项目依赖以树形方式展现出来,你可以看到spring-boot-starter-parent本身并没有提供依赖。编辑pom.xml,并在parent节点下添加spring-boot-starter-web依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

如果再次运行mvn dependency:tree,你将看到现在多了一些其他依赖,包括Tomcat web服务器和Spring Boot自身。

11.3. 编写代码

为了完成应用程序,我们需要创建一个单独的Java文件。Maven默认会编译src/main/java下的源码,所以你需要创建那样的文件结构,并添加一个名为src/main/java/Example.java的文件:

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;

@RestController
@EnableAutoConfiguration
public class Example {

    @RequestMapping("/")
    String home() {
        return "Hello World!";
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Example.class, args);
    }

}

尽管代码不多,但已经发生了很多事情,让我们分步探讨重要的部分吧!

11.3.1. @RestController和@RequestMapping注解

Example类上使用的第一个注解是@RestController,这被称为构造型(stereotype)注解。它为阅读代码的人提供暗示(这是一个支持REST的控制器),对于Spring,该类扮演了一个特殊角色。在本示例中,我们的类是一个web @Controller,所以当web请求进来时,Spring会考虑是否使用它来处理。

@RequestMapping注解提供路由信息,它告诉Spring任何来自"/"路径的HTTP请求都应该被映射到home方法。@RestController注解告诉Spring以字符串的形式渲染结果,并直接返回给调用者。

@RestController@RequestMapping是Spring MVC中的注解(它们不是Spring Boot的特定部分),具体参考Spring文档的MVC章节

11.3.2. @EnableAutoConfiguration注解

第二个类级别的注解是@EnableAutoConfiguration,这个注解告诉Spring Boot根据添加的jar依赖猜测你想如何配置Spring。由于spring-boot-starter-web添加了Tomcat和Spring MVC,所以auto-configuration将假定你正在开发一个web应用,并对Spring进行相应地设置。

Starters和Auto-Configuration:Auto-configuration设计成可以跟"Starters"一起很好的使用,但这两个概念没有直接的联系。你可以自由地挑选starters以外的jar依赖,Spring Boot仍会尽最大努力去自动配置你的应用。

11.3.3. main方法

应用程序的最后部分是main方法,这是一个标准的方法,它遵循Java对于一个应用程序入口点的约定。我们的main方法通过调用run,将业务委托给了Spring Boot的SpringApplication类。SpringApplication将引导我们的应用,启动Spring,相应地启动被自动配置的Tomcat web服务器。我们需要将Example.class作为参数传递给run方法,以此告诉SpringApplication谁是主要的Spring组件,并传递args数组以暴露所有的命令行参数。

11.4. 运行示例

到此,示例应用可以工作了。由于使用了spring-boot-starter-parent POM,这样我们就有了一个非常有用的run目标来启动程序。在项目根目录下输入mvn spring-boot:run启动应用:

$ mvn spring-boot:run

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v1.4.1.BUILD-SNAPSHOT)
....... . . .
....... . . . (log output here)
....... . . .
........ Started Example in 2.222 seconds (JVM running for 6.514)

如果使用浏览器打开localhost:8080,你应该可以看到如下输出:

Hello World!

点击ctrl-c温雅地关闭应用程序。

11.5. 创建可执行jar

让我们通过创建一个完全自包含,并可以在生产环境运行的可执行jar来结束示例吧!可执行jars(有时被称为胖jars "fat jars")是包含编译后的类及代码运行所需依赖jar的存档。

可执行jars和Java:Java没有提供任何标准方式,用于加载内嵌jar文件(即jar文件中还包含jar文件),这对分发自包含应用来说是个问题。为了解决该问题,很多开发者采用"共享的"jars。共享的jar只是简单地将所有jars的类打包进一个单独的存档,这种方式存在的问题是,很难区分应用程序中使用了哪些库。在多个jars中如果存在相同的文件名(但内容不一样)也会是一个问题。Spring Boot采取一个不同的方式,允许你真正的直接内嵌jars。

为了创建可执行的jar,我们需要将spring-boot-maven-plugin添加到pom.xml中,在dependencies节点后面插入以下内容:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

spring-boot-starter-parent POM包含绑定到repackage目标的<executions>配置。如果不使用parent POM,你需要自己声明该配置,具体参考插件文档

保存pom.xml,并从命令行运行mvn package

$ mvn package

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building myproject 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] .... ..
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ myproject ---
[INFO] Building jar: /Users/developer/example/spring-boot-example/target/myproject-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:1.4.1.BUILD-SNAPSHOT:repackage (default) @ myproject ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

如果查看target目录,你应该可以看到myproject-0.0.1-SNAPSHOT.jar,该文件大概有10Mb。想查看内部结构,可以运行jar tvf

$ jar tvf target/myproject-0.0.1-SNAPSHOT.jar

在该目录下,你应该还能看到一个很小的名为myproject-0.0.1-SNAPSHOT.jar.original的文件,这是在Spring Boot重新打包前,Maven创建的原始jar文件。

可以使用java -jar命令运行该应用程序:

$ java -jar target/myproject-0.0.1-SNAPSHOT.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v1.3.0.BUILD-SNAPSHOT)
....... . . .
....... . . . (log output here)
....... . . .
........ Started Example in 2.536 seconds (JVM running for 2.864)

如上所述,点击ctrl-c可以温雅地退出应用。